<?php

/**
 * @author liyi
 * @DateTime 2018.12.29
 * 搬砖大富翁
 */

namespace Monopolygame\Controller;
use Common\Controller\ApiController;
use Think\Model;
use Think\Log;

class IndexController extends ApiController {
    
    const GAME_TYPE = 'Monopolygame';  // 游戏类型

    const USER_UID = "monoly:user:%s:type:%s:qid:%s";  // 用户主键分享到群

    const MONOLY_PLAY = "monolys:play"; // 游戏次数(本游戏没有次数)

    const MONOLY_SHARE = "monolys:share";  // 普通分享次数

    const MONOLY_REVIVE = "monolys:revive"; // 复活分享次数（本游戏没有复活次数）

    const MONOLY_INVITE = "monolys:invite"; // 邀请次数

    const MONOLY_SESSION = "monoly:"; // session_key 判断

    const MONOLY_UPGRADE = "monolys:upgrade";  // 数据跟新次数

    const MONOLY_RANK = "monolys:ranking";  // 排行榜次数

    const MONOLY_RANK_LIST = "monopoly:rankList"; // 排行榜列表

    public function __construct()
    {
        parent::__construct();
        $uid = $this->isLogin(self::MONOLY_SESSION);
        $id = I('id','','int');
        if(empty($uid)) {
            //$uid = $this->isParamLogin($id);
            $uid = $id;
        }
        if (!$uid) {
            $this->response(1,'请先登录');
        }
        $this->uid = $uid;
    }

    // 排行榜
    public function rankingList()
    {
        $uid = $this->uid;
        $gold = I('gold',0,'string');
        $number = I('number',0,'string');
        $brick_level = I('brick_level',0,'int');
        $last_gold = I('last_gold',0,'string');
        $store_level = I('store_level',0,'string');
        
        $param['number'] = $number;
        $param['brick_level'] = $brick_level;
        $param['last_gold'] = $last_gold;
        $param['store_level'] = $store_level;

        $redis = REDIS('activity');
        $redis->select(2);
        $hash_key = self::MONOLY_RANK_LIST;

        $ret = $this->getRankList($hash_key,true,2,'gold');

        $where['status'] = 2;  // 授权用户
        $where['gold'] = array('neq',0);
        $where['black_list'] = 1;
        if(empty($ret)) {
            $ret = M('users')->field('id,nickname,avatar,gold,sort,best_rank')->where($where)->order('sort asc')->limit(200)->select();
            foreach($ret as $k=>$v) {
                if(!empty($v['nickname']) && !empty($v['avatar'])){
                    $id = $v['id'];
                    $flag = $redis->hSet($hash_key,$id, json_encode($v));
                }
            }
        }

        $map['id'] = $uid;
        $userInfo = M('users')->field('id,nickname,avatar,gold,best_rank,last_gold,store_level')->where($map)->find();
        
        if( $gold > $userInfo['gold'] ) {
            $param['gold'] = $gold;

            $data = array('id'=>$userInfo['id'],'gold'=>$gold,'nickname'=>$userInfo['nickname'],'avatar'=>$userInfo['avatar'],'best_rank'=>$userInfo['best_rank']);
            $this->setRankList($hash_key,2,$data,$userInfo['id'],'gold',$gold);

            M('users')->where($map)->save($param);  //点击排行版更新用户数据

            $ret = $this->getRankList($hash_key,true,2,'gold');
            $info = array_column($ret,null,'id');
            $userInfo = $info[$uid];  // 用户信息
            // $userInfo = M('users')->field('id,nickname,avatar,gold,best_rank,last_gold,store_level')->where($map)->find();

            // $ret = M('users')->field('id,nickname,avatar,gold,sort')->where($where)->order('sort asc')->limit(200)->select();
            
            $rankNum = $this->getRank($ret,$userInfo);
      
            if(empty($userInfo['best_rank']) || ($rankNum <= $userInfo['best_rank']) || $rankNum <= 200 ) {  //用户最佳排名
            
                M('users')->where($map)->save(array('best_rank'=>$rankNum,'sort'=>$rankNum));
                //$userInfo['best_rank'] = $rankNum;
                //redis->hSet($hash_key,$id, json_encode($userInfo));
                //$userInfo = M('users')->field('id,nickname,avatar,gold,best_rank,last_gold,brick_level,store_level')->where($map)->find();            
            }

            // if( $rankNum <= 200 ) {  // 记录用户前两百名次的实时变化
            //     M('users')->where($map)->save(array('sort'=>$rankNum));
            // }

        }


        $pop_unit = array_shift($ret);  // 兼容前端DT最大值判断
        if( $pop_unit['gold'] == 'Infinity' ) {
            $redis->hDel($hash_key,$pop_unit['id']);
        }

        // $info = array_column($ret,null,'id');
        // $userInfo = $info[$uid];  // 用户信息
        // $rankNums = $this->getRank($ret,$userInfo);

        $userInfo = M('users')->field('id,nickname,avatar,gold,best_rank,last_gold,brick_level,store_level,sort')->where($map)->find();
        $userInfo['rankNum'] = $userInfo['sort'] > 200 ? 201 : $userInfo['sort'];


        // $ret = M('users')->field('id,nickname,avatar,gold,sort')->where($where)->order('sort asc')->limit(200)->select();
        // $userInfo = M('users')->field('id,nickname,avatar,gold,best_rank,last_gold,brick_level,store_level')->where($map)->find(); 
        // $rankNums = $this->getRank($ret,$userInfo);
        // $userInfo['rankNum'] = $rankNums;
        

        //$this->countLog('monolys',self::MONOLY_RANK);  // 记录排行榜请求次数
        $this->response(0, "OK",array('randList'=>$ret,'userInfo'=>$userInfo));
    }

    // 查看排行榜
    public function getRank($ret,$userInfo) {
        $rankNum = 0; // 排名
        $uid = null;
        if(!empty($ret)) {

            foreach($ret as $k=>$v) {
               
                if( $uid == $v['id'] && $userInfo['gold'] >= $v['gold'] ) {                
                    $rankNum = $k + 1;
                    break;
                }
                
                if( $userInfo['gold'] > $v['gold'] ) {
                    $rankNum = $k + 1;
                    break;
                }
            }   
        }

        if( $rankNum == 0 ) {

            $rankNum = count($ret) + 1 ;
        }
        return $rankNum;
    }

    // 数据跟新接口
    public function upgrade () {

        $uid = $this->uid;
        $gold = I('gold',0,'string');
        $number = I('number',0,'string');
        $brick_level = I('brick_level',0,'int'); // 搬砖等级
        $last_gold = I('last_gold',0,'string');  // 现金金币
        $store_level = I('store_level',0,'string'); // 仓库等级

        $data = array(
            'gold' => $gold,
            'number' => $number,
            'brick_level' => $brick_level,
            'last_gold' => $last_gold,
            'store_level' => $store_level
        );
        $map['id'] = $uid;
        $ret = M('users')->where($map)->save($data);  //点击排行版更新用户数据
        $this->countLog('monolys',self::MONOLY_UPGRADE);  // 记录游戏跟新次数
        $this->response(0,"操作成功");
    }

    // 获取用户邀请列表
    public function getUserInvite()
    {
        $uid = I('id',0,'int');
        $type = I('type',1,'int'); //1:每日邀请
        $map['invite_uid'] = $uid;
        $map['type'] = $type;
        $list = M('invite_log')->field('uid')->where($map)->select();

        $userInfo = array();
        $number = 0;
        if(!empty($list)) {
            $number = intval(count($list));
            $uidArr = array_column($list,'uid');
            $uidStr = implode(',', $uidArr);
            $where['id'] = array('in',$uidStr);
            $userInfo = M('users')->field('id,nickname,avatar')->where($where)->select();
        }
        
        $this->response(0,"ok",array('userInfo'=>$userInfo,'number'=>$number));
    }

    // 获取用户邀请列表
    public function getUserInvite2()
    {
        $uid = I('id',0,'int');
        $type = I('type',1,'int'); //1:每日邀请
        $map['invite_uid'] = $uid;
        $map['type'] = $type;
        $list = M('invite_two')->field('uid')->where($map)->select();

        $userInfo = array();
        $number = 0;
        if(!empty($list)) {
            $number = intval(count($list));
            $uidArr = array_column($list,'uid');
            $uidStr = implode(',', $uidArr);
            $where['id'] = array('in',$uidStr);
            $userInfo = M('users')->field('id,nickname,avatar')->where($where)->select();
        }

        $this->response(0,"ok",array('userInfo'=>$userInfo,'number'=>$number));
    }

    // 邀请接口
    public function inviteRecord()
    {
        $uid = I('id',0,'int');
        $invite_uid = I('invite_uid',0,'int');
        $type = I('type',1,'int');  // 99：无限钻石(新用户);101：转发记录添加;102：转发记录查询;103：转发记录删除
        $time = date('Y-m-d');

        // 转发邀请记录
        $typeForward = array("101","102","103");
        if(in_array($type,$typeForward)){
            $type_table = 'monopoly';   // redis表
            $this->getForward($uid,$invite_uid,$type_table,$type);
        }

        $map['uid'] = $uid;
        $map['create_time'] = $time;
        $user = M('invite_log')->where($map)->find();
        if (!empty($user))
        {
            $this->response(3, "已被邀请过");
        }

        if( $uid != $invite_uid ) {  //如果不是自己邀请自己
            $data['uid'] = $uid;
            if(!empty($invite_uid)) {
                $data['invite_uid'] = $invite_uid;
            }
            $data['create_time'] = $time;
            $data['type'] = $type;
            $ret = M('invite_log')->add($data);
            if(empty($ret)) {

                $this->response(1, "操作失败");
            }
            $this->countLog('monolys',self::MONOLY_INVITE);  // 记录邀请次数日志
        }

        $this->response(0, "操作成功");
    }


    /**
     * 邀请记录
     * @param  int $uid  邀请人编号
     * @param  int $invite_uid 被邀请人编号
     * @return array
     */
    private function _inviteRecord($uid,$invite_uid)
    {
        if(empty($uid) || empty($invite_uid)) {
            $this->response(4, "邀请人与被邀请人不能为空");
        }
        $invite_uid = I('invite_uid',0,'int');
        $type = I('type',1,'int');  // 99：无限钻石(新用户);101：转发记录添加;102：转发记录查询;103：转发记录删除
        $time = date('Y-m-d');

        if(empty($invite_uid)) {
            $this->response(2, "邀请人id不能为空");
        }

        $map['uid'] = $uid;
        $map['create_time'] = $time;
        $user = M('invite_log')->where($map)->find();
        if (!empty($user))
        {
            $this->response(3, "已被邀请过"); 
        }

        if( $uid != $invite_uid ) {  //如果不是自己邀请自己
            // 转发邀请记录
            $typeForward = array("101","102","103");
            if(in_array($type,$typeForward)){
                $type_table = 'monopoly';   // redis表
                $this->getForward($uid,$invite_uid,$type_table,$type);
            }

            $data['uid'] = $uid;
            $data['invite_uid'] = $invite_uid;
            $data['create_time'] = $time;
            $data['type'] = $type;
            $ret = M('invite_log')->add($data);
            if(empty($ret)) {

                $this->response(1, "操作失败");
            }
            $this->countLog('monolys',self::MONOLY_INVITE);  // 记录邀请次数日志         
        }
        
        $this->response(0, "操作成功");
    }

    /**
     * 邀请记录
    */
    public function inviteRecord2()
    {
        $uid = isset($this->uid)?$this->uid:I('post.id');
        $invite_uid = I('invite_uid',0,'int');
        if(empty($uid) || empty($invite_uid)) {
            $this->response(4, "邀请人与被邀请人不能为空");
        }
        $type = I('type',1,'int');  // 1:任务邀请
        $time = date('Y-m-d');

        if(empty($invite_uid)) {
            $this->response(2, "邀请人id不能为空");
        }

        $map['uid'] = $uid;
        $map['create_time'] = $time;
        $user = M('invite_two')->where($map)->find();
        if (!empty($user))
        {
            $this->response(3, "已被邀请过");
        }

        if( $uid != $invite_uid ) {  //如果不是自己邀请自己

            $data['uid'] = $uid;
            $data['invite_uid'] = $invite_uid;
            $data['create_time'] = $time;
            $data['type'] = $type;
            $ret = M('invite_two')->add($data);
            if(empty($ret)) {

                $this->response(1, "操作失败");
            }
            $this->countLog('monolys',self::MONOLY_INVITE);  // 记录邀请次数日志
        }

        $this->response(0, "操作成功");
    }

    /**
     * @param  int $uid  用户编号
     * @param  int $type 分享类型
     * @param  int $openGId 分享群ID
     * @return true
     */
    private function _shareType($uid,$type,$openGId) {  //每日同一群只能分享一次

        $redis = REDIS('activity');
        $userKey = sprintf(self::USER_UID,$uid,$type,$openGId);  //用户主键分享到群
        $time = time();
        $atNoon = date('Y-m-d 11:59:59'); //每日11点59分
        $evening = date('Y-m-d 23:59:59'); //每日23点59分

        // if( $time <= strtotime($atNoon) ) {  // 当天上午
        //     $redis->set($userKey,1);  // 标记
        //     $redis->exprieAt($userKey,strtotime($atNoon)); // 每日11点59分过期
        // }else {  // 当天下午
            $redis->set($userKey,1);  // 标记
            $redis->exprieAt($userKey,strtotime($evening)); // 每日23点59分过期
        //}
        Log::write('群分享成功uid:'.$uid.'|群分享类型：'.$type,'SUCCESS');
    } 

    // 解密数据
    public function cryptData()
    {
        $uid = $this->uid;
        $data = C(self::GAME_TYPE);
        $appid = $data['APPID'];
        $sessionKey = I('sessionKey','','string'); // sessionKey
        $encryptedData = I('encryptedData','','string'); // 加密数据
        $iv = I('iv','','string');
        $iv = urldecode($iv);
        $type = I('type',0,'int');  // type=3 限制每个群只能分享

        $pc = new \Org\Util\WXBizDataCrypt($appid, $sessionKey);
        $errCode = $pc->decryptData($encryptedData, $iv, $data);

        $data = $data ? json_decode($data, true) : '';
        $openGId = isset($data['openGId']) ? $data['openGId'] : 0;

        $redis = REDIS('activity');
        $userKey = sprintf(self::USER_UID,$uid,$type,$openGId);  // 用户主键
      
        $shareKey = $redis->get($userKey);

        if( $shareKey > 0 ) {

            $this->response(2,'每日同一群只能分享两次,以12点为间隔');
        }

        if ($errCode == 0) {

            $this->_shareType($uid,$type,$openGId);

            $this->countLog('monolys',self::MONOLY_SHARE);  // 记录分享次数日志

            $result = $data ? json_decode($data, true) : '';
            $this->response(0, "成功解密",$result);

        } else {
            Log::write('解密失败:'.$errCode.'|失败uid:'.$uid.'|操作类型：'.$type.'|操作值：'.$data,'ERROR');
             
            $this->response(0, "成功解密");

            //$this->response($errCode,"解密失败");          
        }
    }

    // 获取session_key
    public function getSessionKey() {
        $gameType = self::GAME_TYPE;
        $code = I('code','','string');
        if(!$code) {
            $this->response(2,'code不能为空');
        }
        $info = $this->wxAuthor($gameType,$code);
        if(empty($info)) {
            $this->response(1,"操作失败"); 
        }

        $this->response(0,"OK",array('session_key'=>$info['session_key']));
    }

    // 获取邀请好友的数据
    public function pushMsg()
    {
        $uid = $this->uid;
        $invite_uid = I('invite_uid',0,'int');  //被邀请的用户
        $roomId = I('roomId','','string');  // roomid 
       
        $data = array('roomId'=>$roomId,'invite_uid'=>$invite_uid,'channel'=>'monoly');
        $this->_inviteRecord($uid,$invite_uid);  //记录邀请记录

        $jsons['state'] = $this->sendMsg($data);

        $this->ajaxReturn($jsons);
    }

    // 获取邀请好友的数据
    public function pushMsg2()
    {
        $uid = $this->uid;
        $invite_uid = I('invite_uid',0,'int');  //被邀请的用户
        $roomId = I('roomId','','string');  // roomid

        $data = array('roomId'=>$roomId,'invite_uid'=>$invite_uid,'channel'=>'monoly');
        $this->_inviteRecord2($uid,$invite_uid);  //记录邀请记录

        $jsons['state'] = $this->sendMsg($data);

        $this->ajaxReturn($jsons);
    }
    
    // Socket发送数据
    private function sendMsg($contents)
    {
        // 建立socket连接到内部推送端口
        $client = stream_socket_client('tcp://127.0.0.1:5678', $errno, $errmsg, 1);
        // 推送的数据，包含uid字段，表示是给这个uid推送
        
        // 发送数据，注意5678端口是Text协议的端口，Text协议需要在数据末尾加上换行符
        fwrite($client, json_encode($contents)."\n");
        // 读取推送结果
        return fread($client, 8192);
    }


    // 获取服务器当前时间
    public function getServerTime(){
        $time = time();
        $this->response(0, "ok",$time);
    }

    // 转发记录接口 转发次数人数记录
    public function forward(){
        $uid = isset($this->uid)?$this->uid:I('post.id');  // 用户ID
        $type = I('type','','int'); // 1:查询;2:添加;3:删除
        $type_table = 'monopoly';   // redis表
        $invite_uid = I('invite_uid','','int');
        $this->getForward($uid,$invite_uid,$type_table,$type);
    }

}